package com.example.demo.util;

import com.example.demo.config.Constants;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.UUID;
import java.util.regex.Pattern;

/**
 * @Description
 * @ClassName MyStringUtils
 * @Author: jinqi.zhu
 * @Create: 2021/8/2 9:51
 */
public class MyStringUtils {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyStringUtils.class);

    private static final String SET = "set";

    private static final String JAVA_LANG_STRING = "java.lang.String";

    private static final String GET = "get";

    public static int[] parseString(String s) {
        String[] strings = s.split("\\.");
        int[] result = new int[strings.length];
        for (int i = 0; i < strings.length; i++) {
            result[i] = Integer.valueOf(strings[i]);
        }
        return result;
    }

    /**
     * 都不是空，返回true
     */
    public static boolean hasEmpty(Object... objects) {
        if (objects == null) {
            return true;
        }
        for (Object o : objects) {
            if (o == null || "".equals(o)) {
                return true;
            }
        }
        return false;
    }

    /**
     * if(s1>=s2) return true; if(s1<s2) return false;
     *
     * @param s1
     * @param s2
     * @return
     */
    public static boolean judgeVersion(String s1, String s2) {
        if (StringUtils.isBlank(s1) || StringUtils.isBlank(s2)) {
            return !StringUtils.isBlank(s1) || StringUtils.isBlank(s2);
        }
        int[] i1 = parseString(s1);
        int[] i2 = parseString(s2);
        int min = i1.length > i2.length ? i2.length : i1.length;
        for (int i = 0; i < min; i++) {
            if (i1[i] > i2[i]) {
                return true;
            } else if (i1[i] < i2[i]) {
                return false;
            }
            if (i + 1 == min) {
                return i1.length >= i2.length;
            }
        }
        return true;
    }

    /**
     * check s is uuid or not
     *
     * @param s
     * @return
     */
    public static boolean isUUID(String s) {
        if (StringUtils.isBlank(s)) {
            return false;
        }
        try {
            UUID.fromString(s);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * check s is number or not
     *
     * @param s
     * @return
     */
    public static boolean isNumeric(String s) {
        Pattern pattern = Pattern.compile(Constants.NUMERIC_PATTEN);
        return pattern.matcher(s).matches();
    }

    /**
     * "%" -> "\%'
     */
    public static String sqlLikeFilter(String str) {
        str = StringUtils.trimToNull(str);
        return str == null ? null : str.replaceAll("%", "\\\\%");
    }

    /**
     * 用于字段格式化
     *
     * @param target
     * @return
     */
    public static String formatQuery(String target) {
        return StringUtils.isNotBlank(target) ? target.toLowerCase() : null;
    }

    /**
     * 获取对应属性的set方法名
     *
     * @param name
     * @return
     */
    public static String getFieldSetMethod(String name) {
        return StringUtils.isBlank(name) ? "" : SET.concat(name.substring(0, 1).toUpperCase().concat(name.substring(1)));
    }

    /**
     * Object对象中所有String类型属性：去除值中的空格
     *
     * @param object
     */
    public static void deleteStringTypeFieldTrim(Object object) {
        Class target = object.getClass();
        Method[] methods = target.getMethods();
        if (!CollectionUtils.isEmpty(Arrays.asList(methods))) {
            for (Method method : methods) {
                if (method.getName().startsWith(GET) && JAVA_LANG_STRING.equals(method.getGenericReturnType().getTypeName())) {
                    Method methodSet = null;
                    try {
                        methodSet = target.getMethod(SET.concat(method.getName().substring(3)), String.class);
                    } catch (NoSuchMethodException e) {
                        LOGGER.error("No such method exception : {}", e.getMessage());
                    }
                    if (methodSet != null) {
                        try {
                            Object result = method.invoke(object);
                            if (result != null) {
                                methodSet.invoke(object, result.toString().replace(" ", ""));
                            }
                        } catch (IllegalAccessException e) {
                            LOGGER.error("Illegal access exception : {}", e.getMessage());
                        } catch (InvocationTargetException e) {
                            LOGGER.error("Invocation target exception : {}", e.getMessage());
                        }
                    }
                }
            }
        }
    }

    /**
     * 过滤表情emoji
     *
     * @param source
     * @return
     */
    public static String filterEmoji(String source) {
        if (StringUtils.isBlank(source)) {
            return source;
        }
        StringBuilder buf = null;
        int len = source.length();
        for (int i = 0; i < len; i++) {
            char codePoint = source.charAt(i);
            if (isEmojiCharacter(codePoint) && codePoint != 65039 && codePoint != 8205
                 && codePoint != 65533 && codePoint != 9794 && codePoint != 9793 && codePoint != 9792) {
                if (buf == null) {
                    buf = new StringBuilder(source.length());
                }
                buf.append(codePoint);
            }
        }
        if (buf == null) {
            return null;
        } else {
            if (buf.length() == len) {
                return source;
            } else {
                return buf.toString();
            }
        }
    }

    /**
     * 判断是否是表情emoji
     *
     * @param codePoint
     * @return
     */
    private static boolean isEmojiCharacter(char codePoint) {
        return (codePoint == 0x0) || (codePoint == 0x9) || (codePoint == 0xA)
                || (codePoint == 0xD)
                || ((codePoint >= 0x20) && (codePoint <= 0xD7FF))
                || ((codePoint >= 0xE000) && (codePoint <= 0xFFFD))
                || ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));
    }

    /**
     * 字符串去除前后空格
     *
     * @param s
     * @return
     */
    public static String stringToTrim(String s) {
        return StringUtils.isBlank(s) ? "" : s.trim();
    }
}
